﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataAccess;
using System.Web;
using BussinessLogic.Models.Account;
using BussinessLogic.Models;
using BussinessLogic.Models.Administrator;

namespace BussinessLogic.Services
{
    public class AccountService
    {

        public static int GetUserID(string username)
        {
            using (var bdContext = new LicentaEntities())
            {
                return bdContext.Users.Where(u => u.Email == username).First().ID;
            }
        }
        public static Guid? RegisterUser(RegisterModel registerModel)
        {
            Guid? activationHash = null;

            using (var bdContext = new LicentaEntities())
            {
                if (bdContext.Users.Where(p => p.Email == registerModel.Email).Count() != 0)
                    return null;

                activationHash = Guid.NewGuid();
                User user = new User
                {
                    Password = Common.HashPassword(registerModel.Password),
                    Phone = registerModel.PhoneNumber,
                    FirstName = registerModel.FirstName,
                    LastName = registerModel.LastName,
                    Email = registerModel.Email,
                    RoleID = 1,
                    ActivationHash = activationHash
                };

                bdContext.Users.Add(user);
                bdContext.SaveChanges();
            }

            return activationHash;
        }

        public static Guid? RegisterAdmin(CreateAdminModel registerModel)
        {
            Guid? activationHash = null;

            using (var bdContext = new LicentaEntities())
            {
                if (bdContext.Users.Where(p => p.Email == registerModel.Email).Count() != 0)
                    return null;

                activationHash = Guid.NewGuid();
                User user = new User
                {
                    Email = registerModel.Email,
                    RoleID = 0,
                    ActivationHash = activationHash
                };

                bdContext.Users.Add(user);
                bdContext.SaveChanges();
            }

            return activationHash;
        }

        public static bool CompleteRegisterAdmin(RegisterModel registerModel)
        {
            using (var bdContext = new LicentaEntities())
            {
                Guid key = new Guid(registerModel.Key);
                User admin = bdContext.Users.Where(p => p.ActivationHash == key && p.Email == registerModel.Email).FirstOrDefault();
                if (admin == null)
                    return false;

                admin.Password = Common.HashPassword(registerModel.Password);
                admin.Phone = registerModel.PhoneNumber;
                admin.FirstName = registerModel.FirstName;
                admin.LastName = registerModel.LastName;
                admin.ActivationHash = null;

                bdContext.SaveChanges();
            }

            return true;
        }

        [Flags]
        public enum AccountState
        {
            EmailNotExist = 0x00,

            EmailExist = 0x01,
            ActiveAccount = 0x02,
            CorrectPassword = 0x04
        }

        public static AccountState ValidateUser(LogOnModel logOnModel)
        {
            AccountState result;
            using (var bdContext = new LicentaEntities())
            {
                User user = bdContext.Users.Where(u => u.Email == logOnModel.Email).FirstOrDefault();
                if (user == null)
                    return AccountState.EmailNotExist;

                result = AccountState.EmailExist;

                if (user.Password == Common.HashPassword(logOnModel.Password))
                    result = result | AccountState.CorrectPassword;

                if (user.Active)
                    result = result | AccountState.ActiveAccount;
            }
            return result;
        }

        // Activate user and set activationHash = null
        public static bool ActivateUser(string email, Guid key)
        {
            using (var bdContext = new LicentaEntities())
            {
                User user = bdContext.Users.Where(p => p.Email == email && p.ActivationHash == key).FirstOrDefault();

                if (user == null)
                    return false;

                user.ActivationHash = null;
                user.Active = true;

                bdContext.SaveChanges();
            }

            return true;
        }

        // 
        public static bool FindActiveUser(string email)
        {
            using (var bdContext = new LicentaEntities())
            {
                if (bdContext.Users.Where(p => p.Email == email).Count() == 0)
                    return false;
                else
                    return true;
            }
        }

        public static bool ChangePassword(string email, string newPassword, string confirmPassword)
        {
            if (newPassword != confirmPassword)
            {
                return false;
            }

            using (var bdContext = new LicentaEntities())
            {
                User user = bdContext.Users.Where(u => u.Email == email).FirstOrDefault();

                if (user == null)
                    return false;

                user.Password = Common.HashPassword(newPassword);
                user.ChangePasswordHash = null;

                bdContext.SaveChanges();
            }

            return true;
        }

        public static bool ChangePassword(string email, string oldPassword, string newPassword, string confirmPassword)
        {
            if (newPassword != confirmPassword)
            {
                return false;
            }

            using (var bdContext = new LicentaEntities())
            {
                oldPassword = Common.HashPassword(oldPassword);
                User user = bdContext.Users.Where(u => u.Email == email && u.Password == oldPassword).FirstOrDefault();

                if (user == null)
                    return false;

                user.Password = Common.HashPassword(newPassword);

                bdContext.SaveChanges();
            }

            return true;
        }

        public static bool VerifyRecoverPassword(string email, Guid key)
        {
            using (var bdContext = new LicentaEntities())
            {
                User user = bdContext.Users.Where(p => p.Email == email && p.ChangePasswordHash == key).FirstOrDefault();

                if (user == null)
                    return false;

                //user.ActivationHash = null;
                //user.Active = true;

                //bdContext.SaveChanges();
            }

            return true;
        }

        public static Guid? SetRecoverPassword(string email)
        {
            Guid? recoverHash = null;

            using (var bdContext = new LicentaEntities())
            {
                User user = bdContext.Users.Where(p => p.Email == email).FirstOrDefault();

                if (user == null)
                    return null;

                recoverHash = Guid.NewGuid();
                user.ChangePasswordHash = recoverHash;

                bdContext.SaveChanges();
            }

            return recoverHash;
        }



        public static Guid? CreateAdmin(string email)
        {
            Guid? activationHash = null;

            using (var bdContext = new LicentaEntities())
            {
                if (bdContext.Users.Where(p => p.Email == email).Count() != 0)
                    return null;

                activationHash = Guid.NewGuid();
                User user = new User
                {
                    Email = email,
                    RoleID = 0,
                    ActivationHash = activationHash
                };

                bdContext.Users.Add(user);
                bdContext.SaveChanges();
            }

            return activationHash;
        }

        public static List<LockAccountModel> GetAllActiveUsers()
        {
            using (var bdContext = new LicentaEntities())
            {
                var users = (from u in bdContext.Users
                             where u.Active
                             select new LockAccountModel
                             {
                                 UserID = u.ID,
                                 Name = u.FirstName + " " + u.LastName,
                                 UserName = u.Email
                             }).OrderBy(u => u.Name).ToList<LockAccountModel>();
                return users;
            }
        }

        public static bool LockAccount(int id)
        {
            using (var bdContext = new LicentaEntities())
            {
                var user = bdContext.Users.Where(u => u.ID == id).FirstOrDefault();

                if (user == null)
                    return false;

                user.Active = false;
                bdContext.SaveChanges();

                return true;
            }
        }

        public enum UserRole
        {
            Patient = 1,
            Administrator = 2
        }

        public static bool IsUserInRole(string username, UserRole role)
        {
            using (var bdContext = new LicentaEntities())
            {
                var user = bdContext.Users.Where(u => u.Email == username).FirstOrDefault();

                return user == null ? false : user.RoleID == (int)role;
            }
        }

        public static List<UserInfo> GetUsers()
        {
            using (var bdContext = new LicentaEntities())
            {
                var result = new List<UserInfo>();

                foreach (var user in bdContext.Users.Where(u=> u.RoleID != 2))
                {
                    result.Add(new UserInfo
                    {
                        UserId = user.ID,
                        FirstName = user.FirstName,
                        LastName = user.LastName,
                        Email = user.Email,
                        PendingApproval = user.UserStudies.Where(us => !us.IsApproved && us.Study.Sessions.FirstOrDefault() != null).FirstOrDefault() != null
                    });
                }

                return result;
            }
        }

        public static UserDetails GetUserInfo(int id)
        {
            using (var bdContext = new LicentaEntities())
            {
                var user = bdContext.Users.Where(u => u.ID == id ).First();

                var result = new UserDetails
                {
                    FirstName = user.FirstName,
                    LastName = user.LastName,
                    Email = user.Email,
                    Phone = user.Phone,
                    Active = user.Active,
                    ID = user.ID
                };

                result.Studies = new List<UserStudyAdmin>();

                foreach (var uStudy in user.UserStudies)
                {
                    result.Studies.Add(new UserStudyAdmin
                    {
                        StudyId = uStudy.StudyID,
                        IsApproved = uStudy.IsApproved,
                        StudyName = uStudy.Study.Name,
                        Waiting = uStudy.Study.Sessions.Where(s => s.IsForApproval).FirstOrDefault() == null
                    });
                }

                return result;
            }
        }

        public static UserStudyDetails GetUserStudyDetails(int sid, int uid)
        {
            using (var bdContext = new LicentaEntities())
            {
                var studyDetails = new UserStudyDetails();
                studyDetails.Sessions = new List<StudySessions>();
                var user = bdContext.Users.Where(u => u.ID == uid).First();
                studyDetails.UserName = user.FirstName + " " + user.LastName;
                studyDetails.StudyName = bdContext.Studies.Where(s => s.ID == sid).First().Name;

                int i = 0;
                foreach (var session in bdContext.Sessions.Where(s => s.UserID == uid && s.StudyID == sid).OrderBy(s => s.Date))
                {
                    studyDetails.Sessions.Add(new StudySessions
                    {
                        ID = session.ID,
                        Crt = i++,
                        Date = session.Date
                    });
                }

                return studyDetails;
            }
        }

        public static void UnlockAccount(int id)
        {
            using (var bdContext = new LicentaEntities())
            {
                var user = bdContext.Users.Where(u => u.ID == id).FirstOrDefault();

                if (user == null)
                    return;

                user.Active = true;
                bdContext.SaveChanges();

            }
        }
    }
}
